﻿using System;
using System.Collections;
using System.Data;

namespace UwaySoft.EsheetServer.DataLayer
{
    public abstract class RecordReaderAdapter<TRcord> : IRecordReader where TRcord : IDataReader, IDataRecord, IEnumerable
    {
        #region 成员字段

        private readonly TRcord _recordReader;

        #endregion

        #region 属性

        public TRcord RecordReader
        {
            get { return _recordReader; }
        }

        #endregion

        #region 构造函数

        protected RecordReaderAdapter(TRcord rcord)
        {
            _recordReader = rcord;
        }

        #endregion

        #region 公共方法

        protected virtual int GetOrdinal(string fieldName)
        {
            return _recordReader.GetOrdinal(fieldName);
        }

        #endregion

        #region IRecordReader 成员

        public abstract bool HasRecord();

        public bool Read()
        {
            return _recordReader.Read();
        }

        public void Close()
        {
            _recordReader.Close();
        }

        public bool ContainsField(string fieldName)
        {
            try
            {
                _recordReader.GetOrdinal(fieldName);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool IsNull(string fieldName)
        {
            return _recordReader.IsDBNull(GetOrdinal(fieldName));
        }

        public TField Get<TField>(string fieldName)
        {
            switch (typeof(TField).FullName)
            {
                case "System.Boolean": return (TField)(object)GetBoolean(fieldName);
                case "System.Byte": return (TField)(object)GetByte(fieldName);
                case "System.DateTime": return (TField)(object)GetDateTime(fieldName);
                case "System.Decimal": return (TField)(object)GetDecimal(fieldName);
                case "System.Double": return (TField)(object)GetDouble(fieldName);
                case "System.Single": return (TField)(object)GetFloat(fieldName);
                case "System.Guid": return (TField)(object)GetGuid(fieldName);
                case "System.Int16": return (TField)(object)GetShort(fieldName);
                case "System.Int32": return (TField)(object)GetInt(fieldName);
                case "System.Int64": return (TField)(object)GetLong(fieldName);
                case "System.String": return (TField)(object)GetString(fieldName);
                default: return (TField)GetObject(fieldName);
            }
        }

        public object GetObject(string fieldName)
        {
            var index = GetOrdinal(fieldName);
            return _recordReader.IsDBNull(index) ? null : _recordReader.GetValue(index);
        }

        public bool GetBoolean(string fieldName)
        {
            return _recordReader.GetBoolean(GetOrdinal(fieldName));
        }

        public byte GetByte(string fieldName)
        {
            return _recordReader.GetByte(GetOrdinal(fieldName));
        }

        public DateTime GetDateTime(string fieldName)
        {
            return _recordReader.GetDateTime(GetOrdinal(fieldName));
        }

        public decimal GetDecimal(string fieldName)
        {
            return _recordReader.GetDecimal(GetOrdinal(fieldName));
        }

        public double GetDouble(string fieldName)
        {
            return _recordReader.GetDouble(GetOrdinal(fieldName));
        }

        public float GetFloat(string fieldName)
        {
            return _recordReader.GetFloat(GetOrdinal(fieldName));
        }

        public Guid GetGuid(string fieldName)
        {
            return _recordReader.GetGuid(GetOrdinal(fieldName));
        }

        public short GetShort(string fieldName)
        {
            return _recordReader.GetInt16(GetOrdinal(fieldName));
        }

        public int GetInt(string fieldName)
        {
            return _recordReader.GetInt32(GetOrdinal(fieldName));
        }

        public long GetLong(string fieldName)
        {
            return _recordReader.GetInt64(GetOrdinal(fieldName));
        }

        public string GetString(string fieldName)
        {
            var index = GetOrdinal(fieldName);
            return _recordReader.IsDBNull(index) ? null : _recordReader.GetString(index);
        }

        #endregion

        #region IEnumerable 成员

        public IEnumerator GetEnumerator()
        {
            return _recordReader.GetEnumerator();
        }

        #endregion

        #region IDisposable 成员

        public void Dispose()
        {
            Dispose(true);
        }

        private void Dispose(bool dispose)
        {
            if (_recordReader != null && !_recordReader.IsClosed)
            {
                Close();
                _recordReader.Dispose();
            }
            if(dispose)
            {
                GC.SuppressFinalize(this);
            }
        }

        #endregion
    }
}
